package com.example.my2048.game.model;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Random;
import java.lang.Integer;

public class Board {    // 棋盘类
    private Integer[][] tiles;    // 所有贴片
    private final Integer rowNum;    // 行数量
    private final Integer colNum;    // 列数量

    public Board(@NonNull Integer rowNum, @NonNull Integer colNum) {    // 构造方法
        this.tiles = new Integer[rowNum][colNum];
        Random random = new Random();
        for (int i = 0; i < rowNum; i++) {
            for (int j = 0; j < colNum; j++) {
                this.tiles[i][j] = random.nextInt(2) % 2;
            }
        }
        this.rowNum = rowNum;
        this.colNum = colNum;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (obj instanceof Board) {
            if (!this.rowNum.equals(((Board) obj).rowNum) ||
                    !this.colNum.equals(((Board) obj).colNum)) {
                return false;
            }
            for (int i = 0; i < this.rowNum; i++) {
                for (int j = 0; j < this.colNum; j++) {
                    if (!this.tiles[i][j].equals(((Board) obj).tiles[i][j])) {
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }

    public Integer[][] getTiles() {    // 获取所有贴片
        return tiles;
    }

    public Integer getTileAt(@NonNull Integer row, @NonNull Integer col) {
        if (row < 0 || row >= this.rowNum || col < 0 || col >= this.colNum) {
            return 0;
        }
        return this.tiles[row][col];
    }

    public void setTiles(@NonNull Integer[][] tiles) {    // 设置所有贴片
        this.tiles = tiles;
    }

    public void setTileAt(@NonNull Integer row, @NonNull Integer col, Integer value) {
        this.tiles[row][col] = value;
    }

    public Integer getRowNum() {    // 获取行数量
        return this.rowNum;
    }

    public Integer getColNum() {    // 获取列数量
        return this.colNum;
    }

    public void createRandomValue(int randomNum) {
        Random random = new Random();
        int random_size = this.rowNum * this.colNum;
        int[] available_values = {1, 2, 4, 8};
        for (int i = 0; i < randomNum; i++) {
            int index = random.nextInt(random_size);
            int value = available_values[random.nextInt(4)];
            if (this.tiles[index / this.colNum][index % this.colNum] == 0) {
                this.tiles[index / this.colNum][index % this.colNum] = value;
            } else {
                i--;
            }
        }
    }

    public void mergeUp() {    // 向上合并同值贴片
        for (int j = 0; j < this.colNum; j++) {
            while (true) {
                int row1 = this.rowNum - 1;
                while (row1 >= 0 && this.tiles[row1][j] == 0) {
                    row1--;
                }
                if (row1 < 1) {
                    break;
                }
                int row2 = row1 - 1;
                boolean if_merge = false;
                while (row1 >= 0 && row2 >= 0) {
                    int curValue = this.tiles[row1][j];
                    while (row2 >= 0 && this.tiles[row2][j] == 0) {
                        row2--;
                    }
                    if (row2 < 0) {
                        break;
                    }
                    if (this.tiles[row2][j] == curValue) {
                        this.tiles[row2][j] += this.tiles[row1][j];
                        this.tiles[row1][j] = 0;
                        if_merge = true;
                    }
                    row1 = row2;
                    while (row1 >= 0 && this.tiles[row1][j] == 0) {
                        row1--;
                    }
                    row2 = row1 - 1;
                }
                if (!if_merge) {
                    break;
                }
            }
            int row1 = 0, row2 = 0;
            while (row2 < this.rowNum) {
                if (this.tiles[row2][j] != 0) {
                    int curValue = this.tiles[row2][j];
                    this.tiles[row2][j] = 0;
                    row2++;
                    this.tiles[row1][j] = curValue;
                    row1++;
                }
                while (row2 < this.rowNum && this.tiles[row2][j] == 0) {
                    row2++;
                }
            }
        }
        this.createRandomValue(1);
    }

    public void mergeDown() {    // 向下合并同值贴片
        for (int j = 0; j < this.colNum; j++) {
            while (true) {
                int row1 = 0;
                while (row1 < this.rowNum && this.tiles[row1][j] == 0) {
                    row1++;
                }
                if (row1 > this.rowNum - 2) {
                    break;
                }
                int row2 = row1 + 1;
                boolean if_merge = false;
                while (row1 < this.rowNum && row2 < this.rowNum) {
                    int curValue = this.tiles[row1][j];
                    while (row2 < this.rowNum && this.tiles[row2][j] == 0) {
                        row2++;
                    }
                    if (row2 >= this.rowNum) {
                        break;
                    }
                    if (this.tiles[row2][j] == curValue) {
                        this.tiles[row2][j] += this.tiles[row1][j];
                        this.tiles[row1][j] = 0;
                        if_merge = true;
                    }
                    row1 = row2;
                    while (row1 < this.rowNum && this.tiles[row1][j] == 0) {
                        row1++;
                    }
                    row2 = row1 + 1;
                }
                if (!if_merge) {
                    break;
                }
            }
            int row1 = this.rowNum - 1, row2 = this.rowNum - 1;
            while (row2 >= 0) {
                if (this.tiles[row2][j] != 0) {
                    int curValue = this.tiles[row2][j];
                    this.tiles[row2][j] = 0;
                    row2--;
                    this.tiles[row1][j] = curValue;
                    row1--;
                }
                while (row2 >= 0 && this.tiles[row2][j] == 0) {
                    row2--;
                }
            }
        }
        this.createRandomValue(1);
    }

    public void mergeLeft() {    // 向左合并同值贴片
        for (int i = 0; i < this.rowNum; i++) {
            while (true) {
                int col1 = this.colNum - 1;
                while (col1 >= 0 && this.tiles[i][col1] == 0) {
                    col1--;
                }
                if (col1 < 1) {
                    break;
                }
                int col2 = col1 - 1;
                boolean if_merge = false;
                while (col1 >= 0 && col2 >= 0) {
                    int curValue = this.tiles[i][col1];
                    while (col2 >= 0 && this.tiles[i][col2] == 0) {
                        col2--;
                    }
                    if (col2 < 0) {
                        break;
                    }
                    if (this.tiles[i][col2] == curValue) {
                        this.tiles[i][col2] += this.tiles[i][col1];
                        this.tiles[i][col1] = 0;
                        if_merge = true;
                    }
                    col1 = col2 - 1;
                    while (col1 >= 0 && this.tiles[i][col1] == 0) {
                        col1--;
                    }
                    col2 = col1 - 1;
                }
                if (!if_merge) {
                    break;
                }
            }
            int col1 = 0, col2 = 0;
            while (col2 < this.colNum) {
                if (this.tiles[i][col2] != 0) {
                    int curValue = this.tiles[i][col2];
                    this.tiles[i][col2] = 0;
                    col2++;
                    this.tiles[i][col1] = curValue;
                    col1++;
                }
                while (col2 < this.colNum && this.tiles[i][col2] == 0) {
                    col2++;
                }
            }
        }
        this.createRandomValue(1);
    }

    public void mergeRight() {    // 向右合并同值贴片
        for (int i = 0; i < this.rowNum; i++) {
            while (true) {
                int col1 = 0;
                while (col1 < this.colNum && this.tiles[i][col1] == 0) {
                    col1++;
                }
                if (col1 > this.colNum - 2) {
                    break;
                }
                int col2 = col1 + 1;
                boolean if_merge = false;
                while (col1 < this.colNum && col2 < this.colNum) {
                    int curValue = this.tiles[i][col1];
                    while (col2 < this.colNum && this.tiles[i][col2] == 0) {
                        col2++;
                    }
                    if (col2 >= this.colNum) {
                        break;
                    }
                    if (this.tiles[i][col2] == curValue) {
                        this.tiles[i][col2] += this.tiles[i][col1];
                        this.tiles[i][col1] = 0;
                        if_merge = true;
                    }
                    col1 = col2;
                    while (col1 < this.colNum && this.tiles[i][col1] == 0) {
                        col1++;
                    }
                    col2 = col1 + 1;
                }
                if (!if_merge) {
                    break;
                }
            }
            int col1 = this.colNum - 1, col2 = this.colNum - 1;
            while (col2 >= 0) {
                if (this.tiles[i][col2] != 0) {
                    int curValue = this.tiles[i][col2];
                    this.tiles[i][col2] = 0;
                    col2--;
                    this.tiles[i][col1] = curValue;
                    col1--;
                }
                while (col2 >= 0 && this.tiles[i][col2] == 0) {
                    col2--;
                }
            }
        }
        this.createRandomValue(1);
    }

}
